package com.leolian.code.fragment.book.netty.chapter14.codec;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import com.leolian.code.fragment.book.netty.chapter14.msg.NettyMessage;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageEncoder;

public class NettyMessageEncoder extends MessageToMessageEncoder<NettyMessage>{
	
	private MarshallingEncoder marshallingEncoder;
	
	public NettyMessageEncoder() throws IOException {
		this.marshallingEncoder = new MarshallingEncoder();;
	}
	
	@Override
	protected void encode(ChannelHandlerContext ctx, NettyMessage msg, List<Object> out) throws Exception {
		if(msg==null || msg.getHeader()==null) {
			throw new Exception("The encode message is null");
		}
		ByteBuf sendBuf = Unpooled.buffer();
		sendBuf.writeInt(msg.getHeader().getCrcCode());
		sendBuf.writeInt(msg.getHeader().getLength());
		sendBuf.writeLong(msg.getHeader().getSessionId());
		sendBuf.writeByte(msg.getHeader().getType());
		sendBuf.writeByte(msg.getHeader().getPriority());
		sendBuf.writeInt(msg.getHeader().getAttachment().size());
		String key = null;
		byte[] keyArray = null;
		Object value = null;
		for (Map.Entry<String, Object> param : msg.getHeader().getAttachment().entrySet()) {
			// 写入Key
			key = param.getKey();
			keyArray = key.getBytes("UTF-8");
			sendBuf.writeInt(keyArray.length);
			sendBuf.writeBytes(keyArray);
			// 写入Value
			value = param.getValue();
			marshallingEncoder.encode(value, sendBuf);
		}
		key = null;
		keyArray = null;
		value = null;
		if(msg.getBody()!=null) {
			marshallingEncoder.encode(msg.getBody(), sendBuf);
//			if(msg.getBody() instanceof Byte)
//				sendBuf.writeByte((byte)msg.getBody());
		} else {
			sendBuf.writeInt(0);
			sendBuf.setInt(4, sendBuf.readableBytes()-8);
		}
		
		// DEBUG
		byte[] bytes = new byte[sendBuf.readableBytes()];
		sendBuf.readBytes(bytes);
		System.err.println("Encoder: "+Arrays.toString(bytes));
		sendBuf.clear();
		sendBuf.writeBytes(bytes);
		
		out.add(sendBuf);
	}
	
}
